/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO_BUS;

import DataObject.MyColumn;
import DataObject.MyRowData;
import DataObject.TableObject;
import java.util.Vector;
import org.w3c.dom.*;

/**
 *
 * @author MinhNhat
 */
public class MyTable {

    public Element ele;
    Vector ColumnsOfTable;
    public MyColumn PrimaryKey;

    public MyTable(Document doc, String name, Vector header) {
        ColumnsOfTable = header;
        Element root = doc.getDocumentElement();
        // doc.appendChild(root);
        ele = doc.createElement("Table");
        root.appendChild(ele);
        ele.setAttribute("Name", name);

        Element eleHeader = doc.createElement("Header");
        Element eleType = doc.createElement("Type");
        ele.appendChild(eleHeader);
        ele.appendChild(eleType);

        for (int i = 0; i < header.size(); i++) {
            MyColumn column = (MyColumn) header.get(i);
            if (column.isKey) {
                PrimaryKey = column;
                ele.setAttribute("PrimaryKey", column.Name);
            }
            eleHeader.setAttribute(column.Name, String.valueOf(i));
            eleType.setAttribute(column.Name, column.Type);
        }


    }

    public MyTable(Element element) {
        ele = element;
        ColumnsOfTable = GetHeader();
        if (ele.hasAttribute("PrimaryKey")) {
            String NameColumnKey = ele.getAttribute("PrimaryKey");
            for (int i = 0; i < ColumnsOfTable.size(); i++) {
                MyColumn column = (MyColumn) ColumnsOfTable.get(i);
                if (column.Name.compareTo(NameColumnKey) == 0) {
                    PrimaryKey = column;
                    column.isKey = true;
                    break;
                } else {
                    column.isKey = false;
                }
            }
        }
    }

    public boolean InsertData(Document doc, Vector Columns, Vector Values) {

        if (this.PrimaryKey != null) {
            Vector Datas = this.GetData();
            if (Columns.size() == 0) {
                for (int i = 0; i < Datas.size(); i++) {
                    Element data = (Element) Datas.get(i);
                    if (data.getAttribute(PrimaryKey.Name).compareTo(Values.get(PrimaryKey.id).toString()) == 0) {
                        return false;
                    }
                }
            } else {
                for (int i = 0; i < Columns.size(); i++) {
                    String column = (String) Columns.get(i);
                    if (column.compareTo(PrimaryKey.Name) == 0) {
                        for (int j = 0; j < Datas.size(); j++) {
                            Element data = (Element) Datas.get(j);
                            if (data.getAttribute(PrimaryKey.Name).compareTo(Values.get(i).toString()) == 0) {
                                return false;
                            }
                        }
                        break;
                    }
                }
            }

        }
        Element data = doc.createElement("Data");
        ele.appendChild(data);
        //Khong cu the
        if (Columns.size() == 0) {
            for (int i = 0; i < ColumnsOfTable.size(); i++) {
                MyColumn column = (MyColumn) ColumnsOfTable.get(i);
                data.setAttribute(column.Name, (String) Values.get(i));
            }
        } else {
            for (int i = 0; i < ColumnsOfTable.size(); i++) {
                MyColumn column = (MyColumn) ColumnsOfTable.get(i);
                String temp = "";
                for (int j = 0; j < Columns.size(); j++) {
                    if (column.Name.compareTo((String) Columns.get(j)) == 0) {
                        temp = (String) Values.get(j);
                        break;
                    }
                }

                data.setAttribute(column.Name, temp);
            }
        }
        return true;
    }

    public String AddRow(Document doc, TableObject row) {
        Vector Datas = this.GetData();
        for (int i = 0; i < Datas.size(); i++) {
            Element data = (Element) Datas.get(i);
            if (PrimaryKey != null) {
                if (data.getAttribute(PrimaryKey.Name).compareTo(row.getAttributeAt(PrimaryKey.id).toString()) == 0) {
                    return "Duplicate Primary Key";
                }
            }
        }
        Element newData = doc.createElement("Data");
        Vector<MyColumn> Columns = GetHeader();
        for (int i = 0; i < Columns.size(); i++) {
            MyColumn column = Columns.get(i);
            newData.setAttribute(column.Name, row.getAttributeAt(i).toString());
        }
        ele.appendChild(newData);
        return "";
    }

    public boolean DeleteData(Vector Conditions) {
        Vector data = GetData();
        boolean flag = false;
        for (int i = 0; i < data.size(); i++) {
            Element eleData = (Element) data.get(i);
            boolean isRight = false;
            Vector tempConditions = (Vector) Conditions.clone();
            if (MyExpression.GetTheTruth(tempConditions, eleData) == 0) {
                isRight = false;
            } else {
                isRight = true;
            }


            if (isRight) {
                flag = true;
                ele.removeChild(eleData);
            }

        }

        return flag;

    }

    public String DeleteRow(TableObject row) {
        Vector<Element> Datas = this.GetData();
        if (PrimaryKey != null) {
            String key = row.getAttributeAt(PrimaryKey.id).toString();
            for (Element data : Datas) {
                if (data.getAttribute(PrimaryKey.Name).compareTo(key) == 0) {
                    ele.removeChild(data);
                    return "Delete Success!!!";
                }
            }
        } else {
            for (Element data : Datas) {
                boolean flag = false;
                for (int j = 0; j < ColumnsOfTable.size(); j++) {
                    MyColumn column = (MyColumn) ColumnsOfTable.get(j);
                    if (data.getAttribute(column.Name).compareTo(row.getAttributeAt(j).toString()) != 0) {
                        flag = true;
                        break;
                    }
                }

                if (!flag) {
                    ele.removeChild(data);
                    return "Delete Success!!!";
                }
            }
        }
        return "Can't not Delete Data!!!";
    }

    public boolean UpdateData(Vector Conditions, Vector Assignments) {

        Vector data = GetData();
        boolean flag = false;
        for (int i = 0; i < data.size(); i++) {
            Element eleData = (Element) data.get(i);
            boolean isRight = false;

            Vector tempConditions = (Vector) Conditions.clone();

            if (MyExpression.GetTheTruth(tempConditions, eleData) == 0) {
                isRight = false;
            } else {
                isRight = true;
            }

            if (isRight) {
                for (int j = 0; j < Assignments.size(); j++) {
                    MyAssignment assignment = (MyAssignment) Assignments.get(j);
                    if (this.PrimaryKey != null) {
                        if (assignment.Column.compareTo(this.PrimaryKey.Name) == 0) {
                            Vector Datas = this.GetData();
                            for (int k = 0; k < Datas.size(); k++) {
                                Element dataCheck = (Element) Datas.get(k);
                                String KeyOfDataCheck = dataCheck.getAttribute(PrimaryKey.Name);
                                if (KeyOfDataCheck.compareTo(assignment.Value) == 0 && KeyOfDataCheck.compareTo(eleData.getAttribute(PrimaryKey.Name)) != 0) {
                                    return false;
                                }
                            }

                        }
                    }

                    if (eleData.hasAttribute(assignment.Column)) {
                        flag = true;
                        eleData.setAttribute(assignment.Column, assignment.Value);
                    }
                }
            }
        }
        return flag;
    }

    public String UpdateRow(TableObject oldRow, String columnName, Object value) {
        Vector<Element> Datas = this.GetData();
        int IndexOfData = -1;
        if (PrimaryKey != null) {
            if (columnName.compareTo(PrimaryKey.Name) == 0) {
                String CurrentValue = oldRow.getAttributeAt(PrimaryKey.id).toString();
                boolean flag = false;
                Element eleOfRow = null;
                for (Element data : Datas) {
                    String ValueOfColumn = data.getAttribute(PrimaryKey.Name);
                    if (CurrentValue.compareTo(ValueOfColumn) != 0 && ValueOfColumn.compareTo(value.toString()) == 0) {
                        flag = true;
                        break;
                    }

                    if (CurrentValue.compareTo(ValueOfColumn) == 0) {
                        eleOfRow = data;
                    }
                }

                if (!flag) {
                    if (eleOfRow != null) {
                        eleOfRow.setAttribute(columnName, value.toString());
                        return "";
                    } else {
                        return "Can't find Row in Table";
                    }
                } else {
                    return "Duplicate Primary Key!!!";
                }
            } else {
                    for (Element data : Datas) {
                        MyRowData Row = new MyRowData(data,ColumnsOfTable);
                        if(Row.isEqual(oldRow))
                        {
                            data.setAttribute(columnName, value.toString());
                            return "";
                        }   
                }
            }
        } else {
            for (Element data : Datas) {
                        MyRowData Row = new MyRowData(data,ColumnsOfTable);
                        if(Row.isEqual(oldRow))
                        {
                            data.setAttribute(columnName, value.toString());
                            return "";
                        }
            }
        }
       
        return "Can't not Update Data!!!";
    }

    public String GetName() {
        return ele.getAttribute("Name");
    }

    public Vector GetHeader() {
        Vector<MyColumn> Header = new Vector<MyColumn>();
        Element eleHeader = (Element) (ele.getElementsByTagName("Header").item(0));
        Element eleType = (Element) (ele.getElementsByTagName("Type").item(0));
        NamedNodeMap columns = eleHeader.getAttributes();
        NamedNodeMap types = eleType.getAttributes();
        /*
         * for(int i=0;i<columns.getLength();i++) { Node node =columns.item(i);
         * for(int j=0;j<types.getLength();j++) { Node type = types.item(j);
         * if(type.getNodeName().compareTo(node.getNodeName())==0) { MyColumn
         * column= new
         * MyColumn(Integer.parseInt(node.getNodeValue()),node.getNodeName(),type.getNodeValue());
         * Header.add(column); } } }
         */
        while (columns.getLength() != Header.size()) {
            int id = Header.size();
            String Column, Type;
            Column = Type = "";
            for (int i = 0; i < columns.getLength(); i++) {
                Node node = columns.item(i);
                int temp = Integer.parseInt(node.getNodeValue());
                if (temp == id) {
                    Column = node.getNodeName();
                    break;
                }
            }

            for (int i = 0; i < types.getLength(); i++) {
                Node node = types.item(i);
                if (Column.compareTo(node.getNodeName()) == 0) {
                    Type = node.getNodeValue();
                    break;
                }
            }

            MyColumn ColumnOfTable = new MyColumn(id, Column, Type);
            Header.add(ColumnOfTable);
        }

        return Header;
    }

    public Vector GetData() {
        System.out.println(ele.getChildNodes());
        Vector data = new Vector();

        NodeList list = ele.getElementsByTagName("Data");
        for (int i = 0; i < list.getLength(); i++) {
            data.add((Element) list.item(i));
        }
        return data;
    }

    public boolean isContainColumn(String str) {
        for (int i = 0; i < ColumnsOfTable.size(); i++) {
            MyColumn column = (MyColumn) ColumnsOfTable.get(i);
            if (column.Name.compareTo(str) == 0) {
                return true;
            }
        }
        return false;
    }

    public static MyTable GetTableByName(Vector Tables, String str) {
        for (int i = 0; i < Tables.size(); i++) {
            MyTable table = (MyTable) Tables.get(i);
            if (table.GetName().compareTo(str) == 0) {
                return table;
            }
        }
        return null;
    }

    public MyColumn GetColumn(String str) {
        for (int i = 0; i < ColumnsOfTable.size(); i++) {
            MyColumn column = (MyColumn) ColumnsOfTable.get(i);
            if (column.Name.compareTo(str) == 0) {
                return column;
            }
        }
        return null;
    }

    public static MyColumn GetColumn(Vector Tables, String strTable, String strColumn) {
        MyTable table = GetTableByName(Tables, strTable);
        if (table != null) {
            return table.GetColumn(strColumn);
        }
        return null;
    }

    public boolean isRightColumns(Vector Columns) {
        for (int i = 0; i < Columns.size(); i++) {
            boolean flag = false;
            String nameColumn = (String) Columns.get(i);
            for (int j = 0; j < ColumnsOfTable.size(); j++) {
                MyColumn Column = (MyColumn) ColumnsOfTable.get(j);
                if (Column.Name.compareTo(nameColumn) == 0) {
                    flag = true;
                    break;
                }
            }

            if (!flag) {
                return false;
            }

        }

        return true;
    }

    public String[] getTableObjectData(Vector<TableObject> lst, Vector<Class> dataTypes) {
        Vector<MyColumn> Columns = GetHeader();
        int size = Columns.size();
        String[] str = new String[size];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (Columns.elementAt(j).id == i) {
                    if (PrimaryKey != null) {
                        if (Columns.elementAt(i).Name.equalsIgnoreCase(PrimaryKey.Name)) {
                            str[i] = Columns.elementAt(j).Name + "*";
                        } else {
                            str[i] = Columns.elementAt(j).Name;
                        }
                    } else {
                        str[i] = Columns.elementAt(j).Name;
                    }


                    dataTypes.add((Columns.elementAt(j).Type.equalsIgnoreCase("Integer")) ? Integer.class : String.class);
                    break;
                }
            }
        }

        Vector<Element> listData = this.GetData();
        for (int i = 0; i < listData.size(); i++) {
            Element ele = listData.get(i);
            TableObject o = new TableObject(size);
            for (int j = 0; j < size; j++) {
                o.setAttributeAt(j, ele.getAttribute(Columns.elementAt(j).Name), (Class) dataTypes.elementAt(j));
            }
            lst.add(o);
        }
        return str;
    }

    public Vector<TableObject> getDesignInfo() {
        Vector<TableObject> columnInfo = new Vector<>();
        Vector<MyColumn> Columns = GetHeader();
        for (MyColumn i : Columns) {
            boolean key = false;
            String cls = "String";
            if (i.Type.equalsIgnoreCase("Integer")) {
                cls = "Integer";
            }
            if (this.PrimaryKey != null) {
                if (i.id == this.PrimaryKey.id) {
                    key = true;
                }
            }
            Object[] obj = new Object[]{i.Name, cls, key};
            TableObject o = new TableObject(obj);
            columnInfo.add(o);
        }
        return columnInfo;
    }

    public boolean isEmpty() {
        if (ele.getChildNodes().getLength() == 2) {
            return true;
        }
        return false;
    }
}
